<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta http-equiv="content-type"
 content="text/html; charset=ISO-8859-1">
  <title>BNF Converter Java 1.5 Mode</title>
<style type="text/css">
pre {
 background-color: silver;
}
</style>
</head>

<body>
<h2>BNF Converter Java 1.5 Mode</h2>
<p>
<i>By Bj&ouml;rn Bringert, 2005. Based on documentation for the Java
Mode by Michael Pellauer.</i>
</p>

<p>
One of the best features of the LBNF file format is that it is
completely independent of the target programming language. The new
Java 1.5 mode allows the BNF Converter to output a compiler front end
in Java 15 using JLex and CUP.
</p>

<p>
The BNFC Java 1.5 mode was developed for JLex version 1.2.6 and CUP
version
0.10k. The generated Java code requires JDK version 1.5.0 or greater.
</p>
<p>
BNF Converter Homepage: <a
 href="http://www.cs.chalmers.se/%7Emarkus/BNFC/">http://www.cs.chalmers.se/~markus/BNFC/</a>
</p>
<p>
JLex Homepage: <a
 href="http://www.cs.princeton.edu/%7Eappel/modern/java/JLex/">http://www.cs.princeton.edu/~appel/modern/java/JLex/</a>
</p>
<p>
CUP Homepage:
<a href="http://www.cs.princeton.edu/%7Eappel/modern/java/CUP/">http://www.cs.princeton.edu/~appel/modern/java/CUP/</a>
</p>
<h3>USAGE</h3>
<p>
<tt>bnfc [-m] -java1.5 FILENAME.cf</tt>
</p>
<p>
To access the Java 1.5 mode simply pass the -java1.5 command to
bnfc. It uses <tt>FILENAME</tt> as the package
name of the generated Java code. The result will be the following
files:
</p>
<table>
  <tbody>
    <tr>
      <th>Filename</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>Absyn/*.java</td>
      <td>Abstract Syntax tree package (in subdirectory Absyn)</td>
    </tr>
    <tr>
      <td>FILENAME.cup</td>
      <td>CUP file (parser specification)</td>
    </tr>
    <tr>
      <td>Yylex</td>
      <td>JLex file (lexer specification)</td>
    </tr>
    <tr>
      <td>PrettyPrinter.java</td>
      <td>A Pretty Printer for the abstract syntax tree</td>
    </tr>
    <tr>
      <td>VisitSkel.java</td>
      <td>A code skeleton for traversing the syntax tree which uses the
Visitor Design Pattern</td>
    </tr>
    <tr>
      <td>Test.java</td>
      <td>A test program</td>
    </tr>
    <tr>
      <td>Makefile</td>
      <td>Makefile (generated only with the -m flag)</td>
    </tr>
  </tbody>
</table>
<p>
Please ensure that your <tt>$CLASSPATH</tt>
correctly points to <tt>JLex.Main</tt> and <tt> java_cup.Main</tt>.
It may also be useful to include the current working directory in the <tt>$CLASSPATH</tt>.
</p>
<h3>Compiling the Compiler Front End</h3>
<p>
You can use the generated Makefile to compile the generated Java code
with <tt>make</tt> (<tt>gmake</tt> on some systems).
</p>
<p>
If all goes well the following files should be generated:
</p>

<table>
  <tbody>
    <tr>
      <th>File</th>
      <th>Description</th>
    </tr>
    <tr>
      <td>Absyn/*.class</td>
      <td>Abstract syntax class files</td>
    </tr>
    <tr>
      <td>Yylex.java</td>
      <td>Lexer generated by JLex</td>
    </tr>
    <tr>
      <td>Yylex.class</td>
      <td>Compiled lexer class</td>
    </tr>
    <tr>
      <td>parser.java</td>
      <td>Parser generated by CUP</td>
    </tr>
    <tr>
      <td>sym.java</td>
      <td>CUP token symbols</td>
    </tr>
    <tr>
      <td>parser.class, sym.class, <br /> CUP$parser$actions.class</td>
      <td>Compiled parser classes</td>
    </tr>
    <tr>
      <td>PrettyPrinter.class</td>
      <td>Compiled pretty printer</td>
    </tr>
    <tr>
      <td>Test.class</td>
      <td>Compiled test program</td>
    </tr>
  </tbody>
</table>



<h3>Testing the Compiler Front End</h3>

<p>
The Java class <tt>Test.java</tt>
may be used to test the result of the generation. To use it simply give
it the name of a file written in the target language. If parsing is
correct, the abstract syntax tree (in Haskell-like syntax) and
linearized pretty-printed result will be shown.
</p>

<p>
For example, if we had created a subset of Java called Javalette, in 
<tt>Javalette.cf</tt>:
</p>

<pre>
&gt; java Javalette.Test helloworld.jl

Parse Successful!

[Abstract Syntax]

(PDefList [(FuncDef TInt(FFuncName "main")[][(SPrintString "Hello
World"), (SReturn NoExpression)]NoSemicolon)])

[Linearized Tree]

int main () 
{
  printString ("Hello World") ;
  return ;
}
</pre>

<p>
If no argument is given then it attempts to read from stdin.
</p>

<p>
Note that the current directory may need to be included in your 
<tt>$CLASSPATH</tt>.
</p>


<h3>Packages in the Generated Code</h3>

<p>
The BNF Converter generates code that makes use of Java packages. For
example, if your file name was <tt>Javalette.cf</tt>,
then it will generate code with a package name of "Javalette". Because
of this your Java compiler may expect that the current directory name
matches the package name. So in our example above the Java compiler
probably will expect the current directory to be named "Javalette" and
be included in the <tt>$CLASSPATH</tt> somehow.
</p>

<p>
Generation of the Abstract Syntax tree can result in hundreds of
classes (one for each rule in your LBNF file). Therefore they are
placed
in a subpackage called "Absyn". A subdirectory will be created if one
does not already exist.
</p>

<h3>The Abstract Syntax Tree</h3>

<p>
The generated code supports the Visitor Design Pattern.
</p>

<p>
Here is an example. Let us say that we have made a simple LBNF file to
describe lists of boolean expressions, called <tt>BoolExp.cf</tt>:
</p>

<pre>
PROG.           PROG   ::= [EXP] ;

OrExp.          EXP     ::= EXP "||" EXP1 ;
AndExp.         EXP1    ::= EXP1 "&&" EXP2 ;
TVal.           EXP2    ::= "true" ;
FVal.           EXP2    ::= "false" ;

separator EXP ";" ;
coercions EXP 2 ;
</pre>

<p>
The Absyn package will contain the following files:
</p>

<pre>
AndExp.java  EXP.java  FVal.java  ListEXP.java  
OrExp.java  PROG.java  TVal.java
</pre>

<p>
Note that there is one Java class for each Label in the LBNF file. The
top of the tree is <tt>PROG</tt>,
which is just a pointer to the top of a list:
</p>

<pre>
package BoolExp.Absyn; // Java Package generated by the BNF Converter.

public class PROG implements java.io.Serializable
{
  public ListEXP listexp_;

  public PROG(ListEXP p1) { listexp_ = p1; }

  public &lt;R,A&gt; R accept(BoolExp.Absyn.PROG.Visitor&lt;R,A&gt; v, A arg) { return v.visit(this, arg); }

  public interface Visitor &lt;R,A&gt; {
    public R visit(BoolExp.Absyn.PROG p, A arg);
  }
}
</pre>

<p>
The class <tt>ListEXP</tt>
is automatically generated to represent the list of <tt>EXP</tt>. 
Using Java 1.5 generics this is trivial, but we still generate a 
class, so that the list implementation
could be changed without changing any of the code
which uses lists of <tt>EXP</tt>.
</p>

<pre>
package BoolExp.Absyn; // Java Package generated by the BNF Converter.

public class ListEXP extends java.util.LinkedList&lt;EXP&gt; { }
</pre>

<p>
It is interesting to note that <tt>ListEXP</tt> refers to
<tt>EXP</tt>. But <tt>EXP</tt> is an abstract class:
</p>

<pre>
package BoolExp.Absyn; // Java Package generated by the BNF Converter.

public abstract class EXP {
  public abstract &lt;R,A&gt; R accept(EXP.Visitor&lt;R,A&gt; v, A arg);
  public interface Visitor &lt;R,A&gt; {
    public R visit(BoolExp.Absyn.OrExp p, A arg);
    public R visit(BoolExp.Absyn.AndExp p, A arg);
    public R visit(BoolExp.Absyn.TVal p, A arg);
    public R visit(BoolExp.Absyn.FVal p, A arg);
  }
}
</pre>

<p>
Abstract classes represent LBNF Categories, such as <tt>EXP</tt>. If a category does
not have a label with the same name (as <tt>PROG</tt> did in our example)
then it is declared abstract. All Labels of a category are represented
as a subclass of the abstract category. Label names should not match
category names if that category has more than one label.
</p>

<p>Here are <tt>EXP</tt>'s subtypes in our example:</p>

<pre>
package BoolExp.Absyn;

public class AndExp extends EXP
{
  public EXP exp_1, exp_2;

  public AndExp(EXP p1, EXP p2) { exp_1 = p1; exp_2 = p2; }
}
</pre>

<pre>
package BoolExp.Absyn;

public class OrExp extends EXP
{
  public EXP exp_1, exp_2;

  public OrExp(EXP p1, EXP p2) { exp_1 = p1; exp_2 = p2; }
}
</pre>

<pre>
package BoolExp.Absyn;

public class TVal extends EXP
{
  public TVal() { }
}
</pre>

<pre>
package BoolExp.Absyn;

public class FVal extends EXP
{
  public FVal() { }
}
</pre>

<p>The classes also contain some support code for the Visitor design
pattern which is not shown above.</p>


<h3>Using the Skeleton File</h3>

<p>The generated file <tt>VisitSkel.java</tt> shows all the visitors
and their methods. Since the generated Visitor interfaces are
parametrized, their use can vary.</p>

<h3>Known Issues</h3>

<p>
Here is a list of known issues with the BNF Converter's Java Mode.
</p

<h4>Keywords</h4>

<p>
Java contains many more keywords than Haskell, and currently there is
nothing to prevent a programmer from using these keywords in their LBNF
grammar. For example:</p>

<pre>
Static.   Package   ::= Sychronized "." Switch ;
</pre>

<p>
While this will be accepted by BNFC it might result in un-compilable
code, as the Java back-end uses lowercase names for instance
variables. As such programmers should generally avoid matching Label
names with Java keywords, or the name of already existing packages.
</p>

<h4>Reuse of Label Names</h4>

<p>
Reusing label names currently results in a warning from BNFC. However,
for Java this is a much more serious issue, as they are used for class
names. For example:
</p>

<pre>
public class FOO extends BAR
{
 ...
}

public class FOO extends BAZ //OOPS! That's two classes named FOO
{
 ...
}
</pre>


<p>
The best solution is for the programmer to ensure that all label names
are unique and not ignore the BNFC warning.</p>


<h4>JLex Regular Expressions</h4>

<p>
BNFC's regular expressions (for user-defined token types) are exactly
isomorphic to those of Alex for Haskell. Unfortunately JLex regular
expressions are not as expressive as those of Alex. Specifically the
following operators are not supported:</p>

<ul>
<li>Set subtraction (-)</li>
<li>Epsillon (eps)</li>
</ul>

<p>
Currently using those operators in a regular expression will cause
generation of the lexer by JLex to fail. In the future a solution might
be found to this by transforming the regular expression, but currently
the programmer should avoid those operators if they wish to generate
Java code.
</p>

<h4>Shift-Reduce Conflicts in CUP</h4>


<p>
Certain grammar constructs result in shift-reduce conflicts in CUP
that do not result in them in Happy. We are currently investigating
exactly what these differences are and how to resolve them, however
initial investigations seem to indicate that CUP's default policy of
Shifting is sufficient. In the meantime, the generated Makefile is
currently set to tell CUP to expect 100 conflicts before it aborts
parser generation.  Depending on the needs of your project this number
could be made bigger or smaller.
</p>

</body>
</html>
